<template>
  <!-- div的作用:给瀑布流区域设置“垂直滚动条”，使得可以进行上拉操作 -->
  <!-- @scroll:记录滚动条卷起的高度 -->
  <div class="scroll-wrapper" @scroll="remember()" ref="myArticle">
    <!-- B.下拉--刷新组件(下拉包围上拉) -->
    <!--  v-model="isLoading" 设置下拉加载状态的
         true：表示：正在加载，自动修改为真，当发生“下拉”动作时，就变为true
         false：默认值：加载结束时，需要手动修改为false

         @refresh="onRefresh" 事件，当发生“下拉”动作时，该事件自动执行，该事件可以实现数据获取操作

          :success-text="downSuccessText"  下拉完毕提示信息 组件提供的属性
          :success-duration="1500" 下拉完毕提示信息停留时长 组件提供的属性
    -->
    <van-pull-refresh
      v-model="isLoading"
      @refresh="onRefresh"
      :success-text="downSuccessText"
      :success-duration="1500"
    >
      <!-- A.上拉--瀑布流加载效果实现
               1.加载完毕后，瀑布流效果会自动执行(内部会判断当前瀑布流区域没有数据，要执行获取数据)
               2.鼠标上拉动作，当滚动条到达算法底部，会执行
               算法底部：瀑布流认为要加载更多数据的位置
               v-model="loading"：表明是否是及在状态，默认是false(不加载)
               loading：true 表示“加载中”   loading：false 表示“加载完毕”

               :finished:表明瀑布停止了，没有更多数据了，停止加载了
               如果没有数据了，:finished 就设置为true

               finished-text="没有更多了"  瀑布流停止后的，底部文字提示

               @load="onLoad" 是事件，是加载数据的时候执行的
      -->
      <van-list v-model="loading" :finished="finished" finished-text="没有更多了" @load="onLoad">
        <!-- van-cell:单元格组件  独占一行  title：设置单元格标题 -->
        <!-- 返回的art_id是超大整形数字BigNumber 需要转换成字符串 -->
        <van-cell
          v-for="item in articleList"
          :key="item.art_id.toString()"
          :title="item.title"
          @click="$router.push({name:'article',params:{aid:item.art_id.toString()}})"
        >
          <!-- 通过命名插槽方式体现单元格下方的描述信息 -->
          <template slot="label">
            <!-- 图片信息 -->
            <van-grid :border="false" v-if="item.cover.type>0" :column-num="item.cover.type">
              <!-- 封面图片类型：type=0: 没有图片 type=1：1张图片  type=3: 3张图片 -->
              <van-grid-item v-for="(item2,k2) in item.cover.images" :key="k2">
                <!-- van-image:是展示图片的组件 -->
                <!-- lazy-load：图片懒加载效果  需搭配Lazyload使用，Lazyload在main.js中做全局注册 -->
                <!-- 两种使用方式: lazy-load  或  :lazy-load="true"  都是表示该属性接收为true的信息-->
                <van-image width="90" height="90" :src="item2" lazy-load />
              </van-grid-item>
            </van-grid>
            <!-- 文字描述信息 -->
            <p>
              <!--  name="close" 叉号图标是vant组件库提供的  icon组件：线框风格 -->
              <!-- item.art_id.toString():代表被处理文章的id -->
              <!-- 外部已经有click事件了，内部还有click事件
                   内部的click事件执行的时候，外部因为冒泡的原因也会执行，导致内部的事件失效
                   处理：阻止事件冒泡
                   stop:是vue内部的修饰符，可以阻止事件冒泡
               -->
              <van-icon
                name="close"
                style="float:right"
                @click.stop="displayDialog(item.art_id.toString())"
              />
              <span>作者:{{item.aut_name}}</span>
              &nbsp;
              <span>评论 :{{item.comm_count}}</span>
              &nbsp;
              <span>时间:{{item.pubdate | formatTime}}</span>
              &nbsp;
            </p>
          </template>
        </van-cell>
      </van-list>
    </van-pull-refresh>

    <!-- 文章不敢兴趣的弹出层 -->
    <!-- v-model: Dialog组件提供的属性，是否显示弹框，值为布尔值(boolean) -->
    <!-- :articleID="nowArticleID"：把当前目标文章的id传递给子组件 -->
    <more-action
      v-model="showDialog"
      :articleID="nowArticleID"
      @dislikeSuccess="handleDislikeSuccess"
    ></more-action>
  </div>
</template>

<script type="text/javascript">
// 导入获取文章数据的api函数
import { apiArticleList } from '@/api/article.js'

// 导入子组件cm-moreaction
import MoreAction from './com-moreaction.vue'

export default {
  name: 'com-article',
  components: {
    MoreAction
  },
  // 1.简易方式接收
  // props: ['channelID'],
  // 2.高级方式接收
  props: {
    channelID: {
      // type:参数类型  类型限制：String Number Array
      // required:true  表示必须传递的参数
      type: Number,
      required: true
    }
  },
  data () {
    return {
      nowTop: 0, // 记录滚动条卷起的的高度

      nowArticleID: '', // 弹框显示的不感兴趣文章的id

      // 是否显示弹出框
      showDialog: false, // 默认不显示弹框

      // 文章列表数据
      articleList: [],
      // 时间戳条件，这样后期可以灵活发生变化
      ts: Date.now(), // 文章列表分页“时间戳”条件

      // 下拉--刷新标志
      isLoading: false, // 是否处于加载状态

      // 上拉--瀑布流相关成员
      list: [], // 接收加载好的数据
      loading: false, // “加载中...”动画是否显示(加载的时候才设置为true，加载完毕再设置为false)，每次onLoad执行就设置为true，执行完毕就设置为false
      finished: false, // 加载是否停止的标志，false可以继续加载，true瀑布流停止加载，如果后端没有数据可以提供了，就设置该项目为true即可

      // 下拉动作完成的文字提示
      downSuccessText: '' // 文章更新成功 / 文章已经是最新的
    }
  },
  created () {
    // 调用函数，获得真实的文章列表数据
    this.getArticleList()
  },
  // keep-alive 组件激活后就调用的方法
  activated () {
    // 组件再次被激活，设置滚动条卷起的高度为离开时候的位置高度
    if (this.nowTop) {
      this.$refs.myArticle.scrollTop = this.nowTop
    }
  },
  methods: {
    // 获得滚动条卷起的高度，并赋值给nowTop-------------------------------------
    // 滚动条随时滚动，remember随时调用
    remember () {
      this.nowTop = this.$refs.myArticle.scrollTop
    },

    // 对不感兴趣文章的处理---------------------------------------
    handleDislikeSuccess () {
      // 从 articleList 文章列表中把目标的文章给删除
      // [客户端级]删除
      // 目标文章id：nowArticleID
      // 根据 nowArticleID 把其在 articleList 数组中的下标给获得到，
      // findIndex()：是数组的一个方法，可以通过条件获得指定目标在数组列表中的下标序号
      const index = this.articleList.findIndex(item => {
        return item.art_id.toString() === this.nowArticleID
      })
      // 2. 根据下标 从 articleList 中做删除操作
      //    数组.splice(下标,长度) 删除数组的指定元素
      this.articleList.splice(index, 1)
    },

    // 弹出框的显示函数
    displayDialog (artID) {
      this.showDialog = true
      this.nowArticleID = artID
    },

    // 获取文章的列表数据
    async getArticleList () {
      // 调用api获取文章数据(参数：频道id、时间戳)
      const obj = {
        channel_id: this.channelID,
        timestamp: this.ts
      }
      const result = await apiArticleList(obj)
      // console.log(result)
      // this.articleList = result.results

      // 对返回的数据结果做升级，不要直接给到data成员，要把返回结果给到瀑布流里面，在瀑布流里面实现push追加
      // async修饰的函数，这个函数如果有return返回结果，这个结果的类型是一个Promise对象，如果调用这个函数的话，需要加async和await修饰符
      return result
    },

    // 下拉--刷新载入
    async onRefresh () {
      // 1.延迟器0.8秒
      await this.$sleep(800)

      // 2.获得文章列表数据
      const articles = await this.getArticleList()

      // 3.判断是否有获得到最新的文章
      if (articles.results.length > 0) {
        // 有获得到, unshift 数组前置追加元素
        this.articleList.unshift(...articles.results)
        // 更新时间戳
        this.ts = articles.pre_timestamp // 使得继续请求，可以获得下页数据
        this.downSuccessText = '文章更新成功'
      } else {
        // 没有最新的文章了，页面要给与提示
        this.downSuccessText = '文章已经是最新的'
      }
      this.isLoading = false // 下拉动画消失[加载完成了]

      //   setTimeout(() => {
      //     this.onLoad() // 调用上拉获得数据
      //     this.isLoading = false // 暂停拉取，下拉加载完成
      //     this.$toast.success('刷新成功')
      //   }, 1000)
    },

    // 上拉--瀑布流加载执行的方法
    async onLoad () {
      // 设置每次执行时的延迟时间
      // await设置上，作用就是当前的延迟器没有执行完毕，后续代码都等着
      await this.$sleep(1000) // 该延迟器要执行1秒的延迟

      // 真实文章数据与瀑布流结合
      // 1.调用函数，获得真实的文章数据
      // articles 就是上面函数getArticleList()  return出来的result
      // articles的结果就是result的结果 articles:{results:文章列表，pre_timestamp:分页时间戳}
      const articles = await this.getArticleList()

      // 2.对获得的数据做处理
      // data中的articleList不要直接接受数据，要设置“追加”
      // 直接赋值会造成瀑布流不断加载的效果
      // articles.results:[{id,title,xx},{id,title,xx},{id,title,xx}...]
      // ...articles.results  是展开运算符，是把[]去掉，使得内部各个对象成员暴露出来，进而被push追加使用
      // this.articleList.push({id,title,xx},{id,title,xx},{id,title,xx}...)
      if (articles.results.length > 0) {
        this.articleList.push(...articles.results)

        // 更新时间戳,方便获取“下一页”数据
        this.ts = articles.pre_timestamp
      } else {
        // 4.当数据全部追加完毕后，就要停止瀑布动画了
        this.finished = true
      }

      // 3.数据获取到之后，停止上拉动画的加载效果
      this.loading = false

      // 异步更新数据
      // setTimeout 仅做示例，真实场景中一般为 ajax 请求
      // setTimeout(() => {
      //   for (let i = 0; i < 10; i++) {
      //     this.list.push(this.list.length + 1)
      //   }

      // 加载状态结束
      // this.loading = false // '加载中。。'动画清除

      // 数据全部加载完成
      // if (this.list.length >= 40) {
      //   this.finished = true // 没有更多数据，加载完成了，加载动画取消
      // }
      // }, 1000)
    }
  }
}
</script>

<style scoped lang="less" >
// 给上拉列表设置样式
.scroll-wrapper {
  height: 100%;
  overflow-y: auto; // 瀑布流区域如果垂直方向内容过多，会显示滚动条
}
</style>
